////
/// @group app-bar
////

@use "sass:map";

@use "../utils";
@use "../spacing";
@use "../box/box";
@use "../box-shadows";
@use "../interaction/interaction";
@use "../theme/a11y";
@use "../theme/colors";
@use "../theme/theme";
@use "../button/button";
@use "../typography/typography";

/// Set to `true` to disable all the styles
/// @type Boolean
$disable-everything: false !default;

/// Set to `true` to only disable the `position: fixed` styles
/// @type Boolean
$disable-fixed: false !default;

/// Set to `true` to only disable the `position: sticky` styles
/// @type Boolean
$disable-sticky: false !default;

/// Set to `true` to only disable the app bar surface color styles.
/// @type Boolean
$disable-surface-theme: $disable-everything !default;

/// Set to `true` to only disable the dense height styles
/// @type Boolean
$disable-dense: false !default;

/// Set to `true` to only disable the prominent height styles
/// @type Boolean
$disable-prominent-theme: false !default;

/// Set to `true` to only disable the prominent-dense height styles
/// @type Boolean
$disable-prominent-dense: false !default;

/// Set to `true` to disable the styles that offset the app bar based on a
/// visible scrollbar.
///
/// @type Boolean
$disable-scrollbar-offset: false !default;

/// Set to `true` to only disable the styles for offsetting the app bar for a
/// visible toolbar while `position: static`.
///
/// @type Boolean
$disable-static-scrollbar-offset: false !default;

/// Set to `true` to only disable the app bar title styles.
/// @type Boolean
$disable-title: false !default;

/// Sets the `gap` css property to apply spacing between each item.
/// @type Number
$gap: spacing.get-var(xs) !default;

/// The default height for an app bar.
/// @type Number
$height: 3.5rem !default;

/// The default dense height for an app bar.
/// @type Number
$dense-height: 3rem !default;

/// The default prominent height for an app bar.
/// @type Number
$prominent-height: $height * 2 !default;

/// The default dense prominent height for an app bar.
/// @type Number
$prominent-dense-height: $dense-height * 2 !default;

/// The z-index to use when the app bar is `position: fixed` or
/// `position: sticky.
///
/// @type Number
$fixed-z-index: 10 !default;

/// This should be a number from 0 to 24 representing the material design
/// elevation. It is used to generate the correct surface styles with box shadow.
/// @type Number
$fixed-elevation: 2 !default;

/// Allows the app bar to be fixed to the top and bottom of the viewport. If you
/// don't need support for one, remove it from the list.
///
/// @example scss - Removing Top Fixed Position<!-- no-compile -->
///   @use "@react-md/core" with (
///     $app-bar-fixed-positions: (bottom)
///   );
///
/// @type List
$fixed-positions: top bottom !default;

/// The background color to use when `theme="surface"` and using the global light
/// theme
/// @type Color
$light-theme-surface-background-color: theme.$light-theme-surface-color !default;

/// The text color to use when `theme="surface"` and using the global light theme
/// @type Color
$light-theme-surface-color: a11y.contrast-color(
  $light-theme-surface-background-color
) !default;

/// The background color to use when `theme="surface"` and using the global dark
/// theme
/// @type Color
$dark-theme-surface-background-color: if(
  theme.$disable-dark-elevation,
  theme.$dark-theme-surface-color,
  map.get(theme.$dark-elevation-colors, $fixed-elevation)
) !default;

/// The text color to use when `theme="surface"` and using the global dark theme
/// @type Color
$dark-theme-surface-color: colors.$white !default;

/// The default `theme="surface"` background color. You normally don't want to
/// change this value.
/// @type Color
$surface-background-color: theme.get-default-color(
  $light-theme-surface-background-color,
  $dark-theme-surface-background-color
) !default;

/// The default `theme="surface"` text color. You normally don't want to change
/// this value.
/// @type Color
$surface-color: theme.get-default-color(
  $light-theme-surface-color,
  $dark-theme-surface-color
) !default;

/// Horizontal padding for the app bar
/// @type String|Number
$horizontal-padding: spacing.get-var(xs) !default;

/// Vertical padding for the app bar
/// @type String|Number
$vertical-padding: spacing.get-var(none) !default;

/// This value is used to align the first element (normally a button) nicely with
/// other elements on the page.
///
/// @type String|Number
$keyline: 1rem !default;

/// This value is used to align the `AppBarTitle` with other elements on the page
/// (like `ListItem`).
/// @type String|Number
$title-keyline: 4.5rem !default;

/// This is used to align a nav button with an `AppBarTitle` nicely in the
/// `AppBar`.
///
/// 3rem is the icon-button's default size. can't use the variables since it's
/// based on font-size now and `em`
///
/// @type String|Number
$nav-keyline: calc($title-keyline - $horizontal-padding - $gap - 3rem) !default;

/// The available configurable css variables and mostly used internally for the
/// `get-var`, `set-var`, and `use-var` utils.
/// @type List
$variables: (height, surface-background-color, surface-color);

/// @param {String} name - The supported variable name
/// @param {any} fallback [null] - An optional fallback value
/// @returns {String} a `var()` statement
@function get-var($name, $fallback: null) {
  $var: utils.get-var-name($variables, $name, "app-bar");
  @if $fallback {
    @return var(#{$var}, #{$fallback});
  }

  @return var(#{$var});
}

/// @param {String} name - The supported variable name
/// @param {any} value - The value to set the variable to. Supports `null` which
/// will just be a no-op.
@mixin set-var($name, $value) {
  @if $value {
    #{utils.get-var-name($variables, $name, "app-bar")}: #{$value};
  }
}

/// @param {String} property - The css property to apply the variable to
/// @param {String} name [$property] - The supported variable name
/// @param {any} fallback [null] - An optional fallback value if the variable
/// has not been set
@mixin use-var($property, $name: $property, $fallback: null) {
  #{$property}: get-var($name, $fallback);
}

/// Applies the light the variables based on feature flags
@mixin use-light-theme {
  @if not $disable-everything and not $disable-surface-theme {
    @include set-var(
      surface-background-color,
      $light-theme-surface-background-color
    );
    @include set-var(surface-color, $light-theme-surface-color);
  }
}

/// Applies the dark the variables based on feature flags
@mixin use-dark-theme {
  @if not $disable-everything and not $disable-surface-theme {
    @include set-var(
      surface-background-color,
      $dark-theme-surface-background-color
    );
    @include set-var(surface-color, $dark-theme-surface-color);
  }
}

/// Applies the dense height variables
@mixin dense-variables {
  @if not $disable-everything and $dense-height {
    @include set-var(height, $dense-height);
  }
}

/// Conditionally applies the css variables based on feature flags
@mixin variables {
  @if not $disable-everything {
    @include set-var(height, $height);
    @include set-var(surface-background-color, $surface-background-color);
    @include set-var(surface-color, $surface-color);
  }
}

/// Generates all the styles based on feature flags.
///
/// @param {Boolean} disable-layer [false] - Set this to `true` to disable the
/// layer behavior
@mixin styles($disable-layer: false) {
  @if not $disable-everything {
    @include utils.optional-layer(app-bar, $disable-layer) {
      @include theme.default-system-theme {
        @include use-dark-theme;
      }

      .rmd-app-bar {
        @include box.set-var(gap, $gap);
        @include box.set-var(padding-v, $vertical-padding);
        @include box.set-var(padding-h, $horizontal-padding);
        @include use-var(height);

        // since app bars can appear a lot in full page dialogs, setting these flex
        // values allows it be be a direct replacement of the `DialogHeader`
        // component without all the offsets and additional styles needed for fixed
        // app bars.
        flex: 0 0 auto;

        @if not $disable-fixed or not $disable-sticky {
          &--fixed {
            left: 0;
            position: fixed;
            // Note: right and width were added to support the main navigation
            // behavior with toggleable full-height navigation
            right: 0;
            width: auto;
            z-index: $fixed-z-index;
          }

          @if $fixed-elevation and $fixed-elevation != 0 {
            &--elevated {
              @include box-shadows.box-shadow(
                $fixed-elevation,
                $disable-colors: true
              );
            }
          }

          @each $position in $fixed-positions {
            &--#{$position} {
              #{$position}: 0;
            }
          }

          @if not $disable-sticky {
            &--sticky {
              position: sticky;
            }
          }
        }

        &--auto {
          // do not set variable so that child AppBar can maintain their height as needed
          height: auto;
        }

        &--stacked {
          flex-direction: column;
          gap: 0;
          padding: 0;
        }

        @if not $disable-dense {
          &--dense {
            height: $dense-height;
          }
        }

        @if not $disable-prominent-theme {
          &--prominent {
            height: $prominent-height;
          }
        }

        @if not $disable-prominent-dense {
          &--prominent-dense {
            height: $prominent-dense-height;
          }
        }

        @if not $disable-surface-theme {
          &--surface {
            @include use-var(background-color, surface-background-color);
            @include use-var(color, surface-color);
          }
        }

        @if not $disable-scrollbar-offset {
          &--scrollbar-offset {
            padding-right: calc(
              #{$horizontal-padding} + #{utils.scrollbar-size()}
            );
          }

          @if not $disable-static-scrollbar-offset {
            &--static-scrollbar-offset {
              width: calc(100% + utils.scrollbar-size());
            }
          }
        }
      }

      @if not $disable-title {
        .rmd-app-bar-title {
          $title-h-margin: calc($keyline - $horizontal-padding);
          $title-keyline-h-margin: calc($title-keyline - $horizontal-padding);

          flex: 1 1 auto;
          margin: 0 auto 0 $title-h-margin;

          &--keyline {
            margin-left: $title-keyline-h-margin;
          }

          &--nav-keyline {
            margin-left: $nav-keyline;
          }

          @include utils.rtl {
            margin-left: 0;
            margin-right: $title-h-margin;

            &--keyline {
              margin-left: 0;
              margin-right: $title-keyline-h-margin;
            }

            &--nav-keyline {
              margin-left: 0;
              margin-right: $nav-keyline;
            }
          }
        }
      }
    }
  }
}
